﻿using System;
using System.Configuration;
using System.Globalization;

namespace BizElements.Core
{
    /// <summary>Contains framework settings whose value can be configured in <b>appSettings</b> section of the application's configuration file.
    /// Settings affect the behavior of all DBMS providers.</summary>
    public static class Settings
    {
        #region ContainsPredicate.Enabled

        /// <summary>Defines whether <see cref="ContainsPredicate"/> is enabled or whether compatibile LIKE expressions are generated.</summary>
        /// <value><b>true</b> to enable full text search if implemented for target DBMS. <b>false</b> to disable full text search for all DBMSs. Default is <b>true</b>.</value>
        /// <remarks>The feature can be switched on or off in <b>appSettings</b> section of the application's configuration file.
        /// The folowing example shows how to disable the feature:
        /// <code>&lt;add key="BizElements.Core.ContainsPredicate.Enabled" value="false"/&gt;</code></remarks>
        public static readonly bool ContainsPredicateEnabled = ReadContainsPredicateEnabledFromConfig();

        private static bool ReadContainsPredicateEnabledFromConfig()
        {            
            string cfgEnabled = ConfigurationManager.AppSettings["BizElements.Core.ContainsPredicate.Enabled"] ?? "";
            bool disabled = (cfgEnabled.ToLowerInvariant() == "false");
            return !disabled;
        }

        #endregion

        #region EntityDAO.ParentsFetchedInSingleSelect

        /// <summary>Defines whether <see cref="EntityDAO"/> and <see cref="ActiveRecordBase"/> classes fetch all parents in a large single SELECT statement with multiple JOINs.</summary>
        /// <value><b>true</b> to use single SELECT for all parents; <b>false</b> otherwise. Default is <b>false</b>.</value>
        /// <remarks><para>When set to <b>false</b> BizElements will execute multiple, ie. one per parent, atomic SELECTs with parent's PK in WHERE clase. 
        /// When set to <b>true</b> BizElements executes one large SELECT with child's PK in WHERE clause. This reduces the number of round trips to database,
        /// but in some cases performance may be worse.</para>
        /// <para>The feature can be switched on or off in <b>appSettings</b> section of the application's configuration file. 
        /// The folowing example shows how to enable the feature:
        /// <code>&lt;add key="BizElements.Core.EntityDAO.ParentsFetchedInSingleSelect" value="true"/&gt;</code>
        /// </para></remarks>
        public static readonly bool ParentsFetchedInSingleSelect = ReadParentsFetchedInSingleSelectFromConfig();

        private static bool ReadParentsFetchedInSingleSelectFromConfig()
        {
            string cfgParentsFetchedInSingleSelect = ConfigurationManager.AppSettings["BizElements.Core.EntityDAO.ParentsFetchedInSingleSelect"] ?? "";
            return (cfgParentsFetchedInSingleSelect.ToLowerInvariant() == "true");
        }

        #endregion

        #region GenericHierarchicalQueryExecutor.MaxLevel.

        /// <summary>Defines maximum tree depth for <see cref="BizElements.Core.ProviderComponents.GenericHierarchicalQueryExecutor"/>.</summary>
        /// <value>Maximum level. Default is <b>100</b>.</value>
        /// <remarks>The value can configured in <b>appSettings</b> section of the application's configuration file.
        /// <code>&lt;add key="BizElements.Core.GenericHierarchicalQueryExecutor.MaxLevel" value="100"/&gt;</code></remarks>
        public static readonly int GenericHierarchicalQueryExecutorMaxLevel = ReadMaxLevelFromConfig();

        private static int ReadMaxLevelFromConfig()
        {
            const int defaultMaxLevel = 100;
            string cfgMaxLevel = ConfigurationManager.AppSettings["BizElements.Core.GenericHierarchicalQueryExecutor.MaxLevel"];
            ushort parsedMaxLevel;
            bool isValidMaxLevel = ushort.TryParse(cfgMaxLevel, out parsedMaxLevel);
            if (isValidMaxLevel)
                return parsedMaxLevel;
            else
                return defaultMaxLevel;
        }

        #endregion

        #region DefaultCommandTimeout.

        /// <summary>Overrides default wait time before terminating the attempt to execute a command and generating an error.</summary>
        /// <value>The time (in seconds) to wait for the command to execute.</value>
        /// <remarks>The value can configured in <b>appSettings</b> section of the application's configuration file.
        /// <code>&lt;add key="BizElements.Core.DefaultCommandTimeout" value="30"/&gt;</code></remarks>
        public static readonly int? DefaultCommandTimeout = ReadDefaultCommandTimeoutFromConfig();

        private static int? ReadDefaultCommandTimeoutFromConfig()
        {
            int timeout;
            bool isConfigured = int.TryParse(ConfigurationManager.AppSettings["BizElements.Core.DefaultCommandTimeout"], out timeout);
            if (isConfigured)
                return timeout;
            else
                return null;
        }

        #endregion

        #region CommandExecutionStatisticsLogged.

        /// <summary>Defines whether <see cref="CommandExecutionStatistics"/> will write details to <see cref="System.Diagnostics.Trace"/> whenever its <see cref="CommandExecutionStatistics.StopTime()"/> method is invoked.</summary>
        /// <value><b>true</b> to enable tracing; <b>false</b> otherwise. Default is <b>false</b>.</value>
        /// <remarks>The value can configured in <b>appSettings</b> section of the application's configuration file.
        /// <code>&lt;add key="BizElements.Core.CommandExecutionStatisticsLogged" value="true"/&gt;</code></remarks>
        public static readonly bool CommandExecutionStatisticsLogged = ReadCommandExecutionStatisticsLoggedFromConfig();

        private static bool ReadCommandExecutionStatisticsLoggedFromConfig()
        {            
            string cfgCommandExecutionStatisticsLogged = ConfigurationManager.AppSettings["BizElements.Core.CommandExecutionStatisticsLogged"] ?? "";
            return (cfgCommandExecutionStatisticsLogged.ToLowerInvariant() == "true");
        }

        #endregion
    }
}
